---
title: "MySQL 事务隔离等级"
date: 2020-7-10
categories:
- mysql
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orge0fd055">REPEATABLE READ</a></li>
<li><a href="#org9adabe0">MySQL 中的锁</a>
<ul>
<li><a href="#org6119e72">共享锁 （也称为 S 锁）：允许事务读取一行数据</a></li>
<li><a href="#org8c3dc11">独占锁 （也称为 X 锁）：允许事务删除或更新一行数据</a></li>
<li><a href="#org4f31ae3">意向共享锁 （IS）：事务即将给表中的各个行设置共享锁，事务给数据行加 S 锁前必须获得该表的 IS 锁</a></li>
<li><a href="#org0999642">意向排他锁 （IX）：事务即将给表中的各个行设置排他锁，事务给数据行加 X 锁前必须获得该表 IX 锁</a></li>
</ul>
</li>
<li><a href="#org44bb90f">行锁的算法</a>
<ul>
<li><a href="#orgcc941ca">Record Locks</a></li>
<li><a href="#org7e0dd18">Gap Locks</a></li>
<li><a href="#org92c5606">Next-key Locks</a></li>
</ul>
</li>
</ul>
</div>
</div>
<p>
其他等级与SQL标准定义一致
</p>
<blockquote>
<p>
<a href="https://developer.ibm.com/zh/articles/os-mysql-transaction-isolation-levels-and-locks/">https://developer.ibm.com/zh/articles/os-mysql-transaction-isolation-levels-and-locks/</a>
</p>
</blockquote>
<div class="outline-2" id="outline-container-orge0fd055">
<h2 id="orge0fd055">REPEATABLE READ</h2>
<div class="outline-text-2" id="text-orge0fd055">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">tran a</th>
<th class="org-left" scope="col">tran b</th>
<th class="org-left" scope="col"> </th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">begin</td>
<td class="org-left">begin</td>
<td class="org-left"> </td>
</tr>
<tr>
<td class="org-left">select * from</td>
<td class="org-left"> </td>
<td class="org-left">假如没有读取到任何记录</td>
</tr>
<tr>
<td class="org-left"> </td>
<td class="org-left">insert; commit</td>
<td class="org-left">b 写入一条记录并提交</td>
</tr>
<tr>
<td class="org-left">select * from</td>
<td class="org-left"> </td>
<td class="org-left">还是没有任何记录</td>
</tr>
<tr>
<td class="org-left">insert;</td>
<td class="org-left"> </td>
<td class="org-left">如果写入和b一样的记录，且表上有唯一约束，这里a事务就报错了</td>
</tr>
<tr>
<td class="org-left"> </td>
<td class="org-left"> </td>
<td class="org-left"> </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="outline-2" id="outline-container-org9adabe0">
<h2 id="org9adabe0">MySQL 中的锁</h2>
<div class="outline-text-2" id="text-org9adabe0">
</div>
<div class="outline-3" id="outline-container-org6119e72">
<h3 id="org6119e72">共享锁 （也称为 S 锁）：允许事务读取一行数据</h3>
<div class="outline-text-3" id="text-org6119e72">
<p>
使用 SQL 语句 select * from tableName where… lock in share mode; 手动加 S 锁。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org8c3dc11">
<h3 id="org8c3dc11">独占锁 （也称为 X 锁）：允许事务删除或更新一行数据</h3>
<div class="outline-text-3" id="text-org8c3dc11">
<p>
使用 SQL 语句 select * from tableName where… for update; 手动加 X 锁。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org4f31ae3">
<h3 id="org4f31ae3">意向共享锁 （IS）：事务即将给表中的各个行设置共享锁，事务给数据行加 S 锁前必须获得该表的 IS 锁</h3>
</div>
<div class="outline-3" id="outline-container-org0999642">
<h3 id="org0999642">意向排他锁 （IX）：事务即将给表中的各个行设置排他锁，事务给数据行加 X 锁前必须获得该表 IX 锁</h3>
</div>
</div>
<div class="outline-2" id="outline-container-org44bb90f">
<h2 id="org44bb90f">行锁的算法</h2>
<div class="outline-text-2" id="text-org44bb90f">
<p>
InnoDB 存储引擎使用三种行锁的算法用来满足相关事务隔离级别的要求。
</p>
</div>
<div class="outline-3" id="outline-container-orgcc941ca">
<h3 id="orgcc941ca">Record Locks</h3>
<div class="outline-text-3" id="text-orgcc941ca">
<p>
该锁为索引记录上的锁，如果表中没有定义索引，InnoDB 会默认为该表创建一个隐藏的聚簇索引，并使用该索引锁定记录。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org7e0dd18">
<h3 id="org7e0dd18">Gap Locks</h3>
<div class="outline-text-3" id="text-org7e0dd18">
<p>
该锁会锁定一个范围，但是不包括记录本身。可以通过修改隔离级别为 READ COMMITTED 或者配置 innodb_locks_unsafe_for_binlog 参数为 ON 。
</p>
</div>
</div>
<div class="outline-3" id="outline-container-org92c5606">
<h3 id="org92c5606">Next-key Locks</h3>
<div class="outline-text-3" id="text-org92c5606">
<p>
该锁就是 Record Locks 和 Gap Locks 的组合，即锁定一个范围并且锁定该记录本身。InnoDB 使用 Next-key Locks 解决幻读问题。需要注意的是，如果索引有唯一属性，则 InnnoDB 会自动将 Next-key Locks 降级为 Record Locks。
举个例子，如果一个索引有 1, 3, 5 三个值，则该索引锁定的区间为 (-∞,1], (1,3], (3,5], (5,+ ∞) 。
</p>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="date">Date: 2020-7-10</p>
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
